package com.vastcom.fabric.server.action;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.vastcom.fabric.server.service.FabricService;

import com.vastcom.fabric.server.to.Coffee;
import com.vastcom.fabric.server.to.HistoryBlockChain;
import com.vastcom.fabric.server.to.PageParmTo;
import com.vastcom.fabric.server.tools.Const;
import com.vastcom.fabric.server.tools.FabricClient;
import com.vastcom.fabric.server.tools.FileTools;
import com.vastcom.fabric.server.tools.UserContext;
import org.hyperledger.fabric.sdk.*;
import org.hyperledger.fabric.sdk.exception.CryptoException;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.exception.ProposalException;
import org.hyperledger.fabric.sdk.exception.TransactionException;
import org.hyperledger.fabric.sdk.security.CryptoSuite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

@CrossOrigin
@RestController
@RequestMapping("/member/")
public class MemberAction {
        private Logger log= LoggerFactory.getLogger(MemberAction.class);

    @Autowired
    private FabricService fabricService;

    @GetMapping("getMyHfClient")
    @ResponseBody
    public HashMap getMyHfClient() throws Exception{

        HashMap m=new HashMap();

        HFClient temp=fabricService.getHfClient();
        if(temp!=null){
           User u= temp.getUserContext();
           m.put("msg",u.getName());
        }
        else {
            m.put("msg","error");
        }



        return m;
    }


@GetMapping("getOrderer")
    @ResponseBody
    public HashMap getOrderer() throws Exception{
        HashMap m=new HashMap();

        Orderer orderer= fabricService.getOrderer();
        if(orderer!=null){
            m.put("msg","ok");
            m.put("obj",orderer.toString());
        }


        return m;
}


@GetMapping("getPeerTest")
    @ResponseBody
    public HashMap getPeerTest() throws Exception{

        HashMap m=new HashMap();

        Peer temp=fabricService.getPeerByName(Const.PEER_RAW_MATERIA_NAME);
        Peer peer1=fabricService.getPeerByName(Const.PEER_ONE_RAW_MATERIA_NAME);

        if(temp!=null){
            m.put("peer0","ok");
            m.put("obj",temp.toString());
        }
        else {
            m.put("msg","empty");
        }

        if(peer1!=null){
            m.put("peer1","ok");
            m.put("obj",peer1.toString());
        }
        Peer bakep1=fabricService.getPeerByName(Const.PEER_BAKE_NAME);
        if(bakep1!=null){
            m.put("bakep0",bakep1.toString());
        }

        Peer bake2=fabricService.getPeerByName(Const.PEER_ONE_BAKE);
        if(bake2!=null){
            m.put("bake1",bake2.toString());
        }



        return m;

}


@GetMapping("createChannel")
    @ResponseBody
    public HashMap createChannel() throws Exception{

        HashMap m=new HashMap();


    Channel channel=fabricService.createChannel();
    if(channel!=null){
        m.put("msg","ok");
        m.put("obj",channel.getName());
    }
    else {
        m.put("msg","error");
    }


        return m;
}



@GetMapping("initChannel")
    @ResponseBody
    public HashMap initChannel() throws Exception{
        HashMap m=new HashMap();

        boolean flag=fabricService.initChannel();
        if(flag){
            m.put("msg","ok");
        }
        else {
            m.put("msg","error");
        }



        return m;
}

//
//@GetMapping("getChannelByName")
//    @ResponseBody
//    public HashMap getChannleByName() throws Exception{
//
//        HashMap m=new HashMap();
//
//
//        Channel channel=fabricService.getCannelByName("sigma");
//        if(channel!=null){
//            m.put("msg","ok");
//            m.put("obj",channel.getName());
//        }
//        else {
//            m.put("msg","empty");
//        }
//
//
//        return m;
//}



    @GetMapping("getChannelByName")
    @ResponseBody
    public HashMap getChannelByName() throws Exception{

        HashMap m=new HashMap();

            FabricClient fabricClient=new FabricClient(fabricService.getMyUserContext());

            Channel channel=fabricClient.getChannleByName("sigma");
            if(channel!=null){
                m.put("msg","ok");
                m.put("obj",channel.getName());

            }
            else {
                m.put("msg","empty");
            }



        return m;
    }




    @GetMapping("testcode")
    @ResponseBody
    public HashMap testCode() throws Exception{


HashMap m=new HashMap();

        System.out.println("counter app");

        //创建User实例
//        String keyFile = "../solo-network/msp/keystore/user-key.pem";
//        String certFile = "../solo-network/msp/signcerts/user-cert.pem";
//        LocalUser user = new LocalUser("admin","SampleOrg",keyFile,certFile);

        try {
            //创建HFClient实例
            HFClient client = HFClient.createNewInstance();
            client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
            client.setUserContext(fabricService.getMyUserContext());
            Properties properties = new Properties();

            String tlscapath= FileTools.CRYPTO_PATH+FileTools.ORDERER_TLS_FILE;
            properties.setProperty("pemFile",tlscapath);
            Orderer orderer = client.newOrderer("orderer.4media.video",
                    "grpcs://orderer.4media.video:7050",
                    properties
                    );

            //创建通道实例
            Channel channel = client.newChannel("ch2");
            channel.addOrderer(orderer);
            //channel.initialize();

            //Peer peer = fabricService.getPeerByName(Const.PEER_RAW_MATERIA_NAME);

            String tlsfileforpeer=FileTools.CRYPTO_PATH;
           tlsfileforpeer+="peerOrganizations/rawmaterial.4media.video/msp/tlscacerts/tlsca.rawmaterial.4media.video-cert.pem";
                          ///peerOrganizations/rawmaterial.4media.video/msp/tlscacerts/tlsca.rawmaterial.4media.video-cert.pem
            Properties propertiesforpeer=new Properties();
            propertiesforpeer.setProperty("pemFile",tlsfileforpeer);
            Peer peer=client.newPeer("peer0.rawmaterial.4media.video",
                    "grpcs://peer0.rawmaterial.4media.video:7051"
            ,propertiesforpeer);
            channel.addPeer(peer);

            log.warn("peer0path"+tlsfileforpeer);
            Channel cl= channel.initialize();
            if(cl!=null){
                m.put("msg","createChannel ok");
                m.put("obj",cl.toString());
            }
        } catch (CryptoException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (TransactionException e) {
            e.printStackTrace();
        }


        //查询链码
//        QueryByChaincodeRequest req = client.newQueryProposalRequest();
//        ChaincodeID cid = ChaincodeID.newBuilder().setName("counter-cc").build();
//        req.setChaincodeID(cid);
//        req.setFcn("value");
//        ProposalResponse[] rsp = channel.queryByChaincode(req).toArray(new ProposalResponse[0]);
//        System.out.format("rsp message => %s\n",rsp[0].getProposalResponse().getResponse().getPayload().toStringUtf8());
//
//        //提交链码交易
//        TransactionProposalRequest req2 = client.newTransactionProposalRequest();
//        req2.setChaincodeID(cid);
//        req2.setFcn("inc");
//        req2.setArgs("10");
//        Collection<ProposalResponse> rsp2 = channel.sendTransactionProposal(req2);
//        TransactionEvent event = channel.sendTransaction(rsp2).get();
//        System.out.format("txid: %s\n", event.getTransactionID());
//        System.out.format("valid: %b\n", event.isValid());


return m;
    }



    @GetMapping("queryChainCode")
    @ResponseBody
    public HashMap queryChainCode() throws Exception{

        HashMap m=new HashMap();
        UserContext userContext=fabricService.getMyUserContext();

//        Enrollment enrollment= UserUtils.getEnrollment(org2keyPath,org2keyFilename,org2certFoldPath ,org2CertFilename);
//
//        userContext.setEnrollment(enrollment);enrollment

        FabricClient fabricClient=new FabricClient(userContext);

        //Peer peer0 = fabricClient.getPeer("peer0.org2.example.com","grpcs://peer0.org2.example.com:9051",tlsPeerFilePathAddtion);
        //Peer peer1 = fabricClient.getPeer("peer1.org2.example.com","grpcs://peer1.org2.example.com:10051",tlsPeerFilePathAddtion);
        Peer peer=fabricClient.getPeerByName(Const.PEER_RAW_MATERIA_NAME);

        List<Peer> peers = new ArrayList<Peer>();
        peers.add(peer);
        //peers.add(peer1);
        String initArgs[] ={"666888"};
        m=fabricClient.queryChaincode(peers,"mychannel", TransactionRequest.Type.GO_LANG
                ,"basicInfo","query",initArgs);





        return m;
    }




    @GetMapping("queryChainCodeTest")
    @ResponseBody
    public HashMap queryChainCodeTest() throws Exception{

        HashMap m=new HashMap();
        UserContext userContext=fabricService.getMyUserContext();

//        Enrollment enrollment= UserUtils.getEnrollment(org2keyPath,org2keyFilename,org2certFoldPath ,org2CertFilename);
//
//        userContext.setEnrollment(enrollment);enrollment

        FabricClient fabricClient=new FabricClient(userContext);

        //Peer peer0 = fabricClient.getPeer("peer0.org2.example.com","grpcs://peer0.org2.example.com:9051",tlsPeerFilePathAddtion);
        //Peer peer1 = fabricClient.getPeer("peer1.org2.example.com","grpcs://peer1.org2.example.com:10051",tlsPeerFilePathAddtion);
        Peer peer=fabricClient.getPeerByName(Const.PEER_RAW_MATERIA_NAME);

        List<Peer> peers = new ArrayList<Peer>();
        peers.add(peer);
        //peers.add(peer1);
        String initArgs[] ={"init"};
        m=fabricClient.queryChaincode(peers,"mychannel", TransactionRequest.Type.GO_LANG
                ,"zzytest","get",initArgs);





        return m;
    }


    @PostMapping("testChainQuery")
    @ResponseBody
    public HashMap testChainQuery(@RequestParam("parm")String parm) throws Exception{

        HashMap m=new HashMap();

        UserContext userContext=fabricService.getMyUserContext();
        FabricClient fabricClient=new FabricClient(userContext);
        Peer peer=fabricClient.getPeerByName(Const.PEER_RAW_MATERIA_NAME);

        List<Peer> peers = new ArrayList<Peer>();
        peers.add(peer);
        //peers.add(peer1);
        String initArgs[] ={parm};
        m=fabricClient.queryChaincode(peers,"mychannel", TransactionRequest.Type.GO_LANG
                ,"zzytest","get",initArgs);


        return m;
    }



    @PostMapping("invoke")
    @ResponseBody
    public HashMap invoke(@RequestParam("key")String key,@RequestParam("value")String value) throws Exception{
        HashMap m=new HashMap();
        try {

            FabricClient fabricClient=new FabricClient(fabricService.getMyUserContext());
            Peer peer0=fabricClient.getPeerByName(Const.PEER_RAW_MATERIA_NAME);

            List<Peer> peerList=new ArrayList<>();
            peerList.add(peer0);

            Orderer orderer=fabricClient.getOrder();

            //String initArgs[]={"\"110114\",\"{\\\"name\\\":\\\"zhangsan\\\",\\\"identity\\\":\\\"110114\\\",\\\"mobile\\\":\\\"18910012222\\\"}\"}"};
            String initArgs[]={"a",key,value};
            //boolean flag= fabricClient.invoke("test", TransactionRequest.Type.GO_LANG,"basicinfo",orderer,peerList,"invoke",initArgs);
            boolean flag=fabricClient.invoke("mychannel", TransactionRequest.Type.GO_LANG,"zzytest",orderer,peerList,"set",initArgs);
            if(flag){
                m.put("msg","ok");
            }
            else {
                m.put("msg","error");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

        return m;
    }




    @PostMapping("getHistoryByKey")
    @ResponseBody
    public HashMap getHistoryByKey(@RequestParam("key")String key) throws Exception{

        HashMap m=new HashMap();

        UserContext userContext=fabricService.getMyUserContext();
        FabricClient fabricClient=new FabricClient(userContext);
        Peer peer=fabricClient.getPeerByName(Const.PEER_RAW_MATERIA_NAME);

        List<Peer> peers = new ArrayList<Peer>();
        peers.add(peer);
        //peers.add(peer1);
        String initArgs[] ={key};
        m=fabricClient.queryChaincode(peers,"mychannel", TransactionRequest.Type.GO_LANG
                ,"zzytest","gethistory",initArgs);


        return m;
    }

    @PostMapping("getHistoryByKeyForHistory")
    @ResponseBody
    public HashMap getHistoryByKeyForHistory(@RequestBody PageParmTo pageParmTo) throws Exception{

        HashMap m=new HashMap();
        HashMap result=new HashMap();
//        log.info("MEMBERgetHistoryByKeyForHistory=================");
        UserContext userContext=fabricService.getMyUserContext();
        FabricClient fabricClient=new FabricClient(userContext);
        Peer peer=fabricClient.getPeerByName(Const.PEER_RAW_MATERIA_NAME);

        List<Peer> peers = new ArrayList<Peer>();
        peers.add(peer);
        //peers.add(peer1);
        String initArgs[] ={pageParmTo.getParm()};
        log.info("MEMBERgetHistoryByKeyForHistory++++++++++++++++"+pageParmTo.getParm());

        m=fabricClient.queryChaincode(peers,"mychannel", TransactionRequest.Type.GO_LANG
                ,"zzytest","gethistory",initArgs);
        String strtemp="";
        if(m.get("result")!=null){
            strtemp= (String) m.get("result");
            strtemp.replace("\\","");
            List<HistoryBlockChain> list = new Gson().fromJson(strtemp, new TypeToken<List<HistoryBlockChain>>() {
            }.getType());
            result.put("list",list);
            result.put("msg","ok");
        }else{
            result.put("msg","error");
        }

        return result;
    }



    @PostMapping("invokeByJson")
    @ResponseBody
    public HashMap invokeByJson(@RequestParam("key")String key,@RequestParam("value")String value) throws Exception{
        HashMap m=new HashMap();
        try {

            FabricClient fabricClient=new FabricClient(fabricService.getMyUserContext());
            Peer peer0=fabricClient.getPeerByName(Const.PEER_RAW_MATERIA_NAME);

            List<Peer> peerList=new ArrayList<>();
            peerList.add(peer0);

            Orderer orderer=fabricClient.getOrder();

            //String initArgs[]={"\"110114\",\"{\\\"name\\\":\\\"zhangsan\\\",\\\"identity\\\":\\\"110114\\\",\\\"mobile\\\":\\\"18910012222\\\"}\"}"};
            String initArgs[]={"a",key,value};
            //boolean flag= fabricClient.invoke("test", TransactionRequest.Type.GO_LANG,"basicinfo",orderer,peerList,"invoke",initArgs);
            boolean flag=fabricClient.invoke("mychannel", TransactionRequest.Type.GO_LANG,"zzytest",orderer,peerList,"setjsondata",initArgs);
            if(flag){
                m.put("msg","ok");
            }
            else {
                m.put("msg","error");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

        return m;
    }



    @GetMapping("testSaveJsonObj")
    @ResponseBody
    public HashMap testSaveJsonObj() throws Exception{

        HashMap m=new HashMap();


        FabricClient fabricClient=new FabricClient(fabricService.getMyUserContext());
        Peer peer0=fabricClient.getPeerByName(Const.PEER_RAW_MATERIA_NAME);

        List<Peer> peerList=new ArrayList<>();
        peerList.add(peer0);

        Orderer orderer=fabricClient.getOrder();

        //String initArgs[]={"\"110114\",\"{\\\"name\\\":\\\"zhangsan\\\",\\\"identity\\\":\\\"110114\\\",\\\"mobile\\\":\\\"18910012222\\\"}\"}"};

        Coffee coffee=new Coffee();
        coffee.setScpc("2021年第66批");
        coffee.setScrq(new Timestamp(System.currentTimeMillis()).getTime());
        coffee.setYlsd("云南大理");
        coffee.setBcwd("65度");
        String jsonstr=new Gson().toJson(coffee);

        String initArgs[]={"a","testjsonkey",jsonstr};
        //boolean flag= fabricClient.invoke("test", TransactionRequest.Type.GO_LANG,"basicinfo",orderer,peerList,"invoke",initArgs);
        boolean flag=fabricClient.invoke("mychannel", TransactionRequest.Type.GO_LANG,"zzytest",orderer,peerList,"set",initArgs);
        if(flag){
            m.put("msg","ok");
        }
        else {
            m.put("msg","error");
        }


        return m;
    }


    @GetMapping("getChainCodeInfo")
    @ResponseBody
    public HashMap getChainCodeInfo() throws Exception{

        HashMap m=new HashMap();

        try {
            FabricClient fabricClient=new FabricClient(fabricService.getMyUserContext());
            Channel channel=fabricClient.getChannleByName("mychannel");
            Orderer orderer=fabricClient.getOrder();
            Peer peer=fabricService.getPeerByName(Const.PEER_RAW_MATERIA_NAME);
            log.info("peer====================");
            channel.addOrderer(orderer);
            channel.addPeer(peer);
            channel= channel.initialize();
            BlockchainInfo blockchainInfo= channel.queryBlockchainInfo();
            if(blockchainInfo!=null){

                Long height=blockchainInfo.getHeight();
                String currenthash=blockchainInfo.getCurrentBlockHash().toString();
                String blockinfo=blockchainInfo.toString();

                m.put("msg","ok");
                m.put("height",height);
                m.put("currenthash",currenthash);
                m.put("blockinfo",blockinfo);


            }
            else {
                m.put("msg","empty");
            }
        } catch (ProposalException e) {
            e.printStackTrace();
            m.put("msg","ProposalException");
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
            m.put("msg","InvalidArgumentException");

        }


        return m;
    }


    @PostMapping("deleteChaincode")
    @ResponseBody
    public HashMap deleteChainCode(@RequestParam("key") String key) {

        HashMap m=new HashMap();

return m;
    }




}
